﻿#ifndef VIRTUALKEYBOARD_H
#define VIRTUALKEYBOARD_H

/*
使用说明： 使用Qwidget实现QT键盘，已经实现的功能：中英文切换、中文词组支持、中英文基础符号、自动弹出虚拟键盘
本工程下有一个Resources文件夹，下面有一个已经制作好的汉字数据库，需要将其放到可执行文件目录下才可正常使用汉字功能
所有样式功能均在资源文件中的QSS中实现

如何实现中文词组：使用数据库的模糊搜索方式，实现中文词组，并自己制作汉字数据库。

本次更新，删除了自定义的 label qpushbutton, 同时解决了在输入过程中光标不可见的问题。并使用一些比较方便的函数：
    connect(qApp, &QApplication::focusChanged, this, &VirtualKeyBoard::focusChangedSlot);//来完成键盘响应
    QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier, QString()); //完成文本删除
    QKeyEvent keyPress(QEvent::KeyPress, 0, Qt::NoModifier, QString(str));//完成文本内容的插入

    比较重要的几个函数：
    getChineseListMap           // 获取汉字词组
    focusChangedSlot            // 自动弹出键盘
    InsertTextToCurFocusWt      // 向控件插入文本
    DeleteTextFromCurFocusWt    // 向控件删除一个字符
*/

#include <QWidget>
#include <QMap>
#include <QMessageBox>
#include <QEvent>
#include <QMutex>

#include "testKeyboard.h"

class QPushButton;
class QSqlDatabase;
class QLineEdit;
class QLabel;

namespace Ui {
class VirtualKeyBoard;
}

class VirtualKeyBoard : public QWidget
{
    Q_OBJECT

public:
    // 获取虚拟键盘实例
    static VirtualKeyBoard *getKeyboard();

    // 初始化虚拟键盘，传入数据库路径
    void initSql(const QString& db_path);

    // 析构函数
    ~VirtualKeyBoard() override;

protected:
    // 显示事件处理
    void showEvent(QShowEvent *event) override;
    // 隐藏事件处理
    void hideEvent(QHideEvent *event) override;
    // 鼠标按下事件处理
    void mousePressEvent(QMouseEvent *e) override;
    // 鼠标移动事件处理
    void mouseMoveEvent(QMouseEvent *e) override;
    // 鼠标释放事件处理
    void mouseReleaseEvent(QMouseEvent *e) override;

private:
    // 构造函数，私有化以实现单例模式
    explicit VirtualKeyBoard(QWidget *parent = nullptr);
    // 禁用拷贝构造函数和赋值运算符
    VirtualKeyBoard(const VirtualKeyBoard&) = delete;
    VirtualKeyBoard& operator=(const VirtualKeyBoard&) = delete;
    // 禁用移动构造函数和移动赋值运算符
    VirtualKeyBoard(VirtualKeyBoard&&) = delete;
    VirtualKeyBoard& operator=(VirtualKeyBoard&&) = delete;
    // 静态成员变量，指向唯一的虚拟键盘实例
    static VirtualKeyBoard* m_keyboard;
    // 互斥锁，用于线程安全
    static QMutex m_mutex;

    // 模拟睡眠函数
    void Sleep(int msec);
    void initQss();
    // 初始化UI中的变量及信号与槽
    void initControl();
    // 清除拼音等缓存
    void clearBuffer(); 
    // 切换大小写
    void switchLetterStatus(); 
    // 显示当前输入的拼音
    void ShowPinYinTip(); 
    // 向控件插入文本
    void InsertTextToCurFocusWt(const QString& str);
    // 向控件删除一个字符
    void DeleteTextFromCurFocusWt();
    // 处理所有虚拟键盘的按钮
    void recKeyClicked(const QString& str);

    // 切换不同符号页
    void setSymbolPage(int enNum_chNum);

private:
    Ui::VirtualKeyBoard *ui;

    // 键盘处理的界面
    testKeyboard m_testKeyboard;

    // 显示当前输入文本的标签
    QLabel* lb_display_text_ = nullptr;
    // 是否隐藏标志
    bool isKeyboardHide = false;
    // 记录鼠标最后的位置
    QPoint mouseLastPosition;
    // 计数器
    int i = 0;

    // 记录当前焦点控件
    QWidget* cur_focus_wt_ = nullptr; 

    // 获取汉字列表
    QMap<int, QStringList> getChineseListMap(const QString &cur_text); 

    // 数据库对象
    QSqlDatabase* db_ = nullptr;
    // 当前拼音页码
    int cur_py_page_ = -1;
    // 上一次保存的可寻找到汉字的拼音组合
    QString last_py_{};
    // 当前输入的拼音文本
    QString cur_py_text_{};
    // 用于确定退格按钮
    QString last_py_text_{};

    // 按钮行枚举
    enum {row_1, row_2, row_3, row_4, row_5};
    // 按钮列表映射
    QMap<int, QList<QPushButton*>> btn_list_map_;

    // 按钮显示文本模式枚举
    enum {en0, en1, en2, ch0, ch1, ch2}; 
    // 当前符号页码
    int symbal_page_ = en0;
    // 符号列表映射
    QMap<int, QStringList>symbol_list_map_ = {};

    // 模式标志映射
    enum {is_ch_mode, is_capital_mode};
    QMap<int, bool>mode_flag_map_{};

private slots:
    // 显示汉字
    void showChinese(const QString &key, const QMap<int, QStringList> &chinese_list_map);
    // 处理所有虚拟键盘的按钮
    void recKeyClickedSlot(); 
    // 选择汉字
    void selectChinese();
    // 处理 qApp 过来的内容
    void focusChangedSlot(QWidget *old, QWidget *now);


public slots:
    // 显示虚拟键盘
    void show();
    // 隐藏虚拟键盘
    void hide();

    // 控制按键处理
    void ControlPressSlot(QWidget *now);

signals:
    // 表示当前外部输入源文本已经被改变
    void changedOutSideTextSignal(const QString &text, const QString &objName); 
    // 设置默认颜色信号
    void setDefaultColorSignal();
};

#endif // VIRTUALKEYBOARD_H
